package com.ycg.vue.utils;

import com.ycg.vue.Enum.WeatherEnum;
import com.ycg.vue.config.WeatherConfig;
import com.ycg.vue.result.WeatherResponse;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.time.LocalDate;

/**
 * @Description 天气工具类(service类)
 * @Author jink
 * @Date 2024/8/28
 */
@Service
public class WeatherUtils extends WeatherConfig {

    private final RestTemplate restTemplate;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    public static final Long ttl = 23L;

    public WeatherUtils(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public WeatherResponse getWeather(String location) {
        try {
            return restTemplate.getForObject(String.format("%s/forecast.json?key=%s&q=%s&days=1", url, key, location), WeatherResponse.class);
        } catch (RestClientException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public String getWeatherByString(String location) {
        String redisKey = "weather-" + location + ":" + LocalDate.now().getMonthValue() + ":" + LocalDate.now().getDayOfMonth();
        Object result = redisTemplate.opsForValue().get(redisKey);
        if (result != null) return result.toString().trim();
        return buildWeatherMessage(location, redisKey);
    }

    private String buildWeatherMessage(String location, String redisKey) {
        WeatherResponse weather = getWeather(location);
        LocalDate today = LocalDate.now();
        WeatherResponse.ForecastDay forecast = weather.getForecast().getForecastday().get(0);
        WeatherResponse.Current current = weather.getCurrent();
        WeatherResponse.Astro astro = forecast.getAstro();

        double maxTemp = forecast.getDay().getMaxtemp_c();
        double minTemp = forecast.getDay().getMintemp_c();
        double tempDifference = maxTemp - minTemp;

        StringBuilder msg = new StringBuilder();
        msg.append(String.format("早上好呀, 今天是%d年%d月%d日，", today.getYear(), today.getMonthValue(), today.getDayOfMonth()))
                .append("今日天气：").append(WeatherEnum.getNameByType(current.getCondition().getText())).append(",")
                .append(String.format("最高温度：%.1f℃, 最低温度：%.1f℃, 温差：%.1f℃,", maxTemp, minTemp, tempDifference));

        if (tempDifference >= 10) {
            msg.append("今日温差较大，多带件衣服再出门哦！");
        }

        msg.append(String.format("当前温度：%.1f℃, 体感温度：%.1f℃, 当前湿度：%.1f%%,", current.getTemp_c(), current.getFeelslike_c(), current.getHumidity()))
                .append(String.format("紫外线强度：%.1f,", current.getUv()))
                .append("风向：").append(convertWindDirection(Integer.parseInt(current.getWind_degree()))).append(",")
                .append("风力：").append(convertWindSpeed(current.getWind_kph())).append(",")
                .append(String.format("云量：%.1f%%,", current.getCloud()))
                .append("日出时间：").append(astro.getSunrise()).append(", ")
                .append("日落时间：").append(astro.getSunset()).append(", ")
                .append("月升时间：").append(astro.getMoonrise()).append(", ")
                .append("月落时间：").append(astro.getMoonset()).append(", ")
                .append("月相：").append(WeatherEnum.getNameByType(astro.getMoon_phase())).append(",")
                .append("出行建议：").append(getClothingAndSunProtectionAdvice(current.getUv()))
                .append("（此邮件为自动提醒，请勿回复！）");

        redisTemplate.opsForValue().set(redisKey, msg.toString(), ttl);
        return msg.toString();
    }


    public String getClothingAndSunProtectionAdvice(double uvIndex) {
        if (uvIndex <= 2) {
            return "今天紫外线指数较低，建议穿普通的日常衣物。可以涂抹少量防晒霜。";
        } else if (uvIndex <= 5) {
            return "今天紫外线指数中等，建议佩戴帽子和太阳镜。或者带着遮阳伞，建议涂抹SPF15-30的防晒霜，特别是在中午时段。";
        } else if (uvIndex <= 7) {
            return "今天紫外线指数较高，建议穿防晒服或长袖长裤，佩戴宽檐帽和太阳镜。或者带着遮阳伞，建议涂抹SPF30-50的防晒霜，并且每隔两小时补涂一次。";
        } else if (uvIndex <= 10) {
            return "今天紫外线指数很高，建议避免在中午时段长时间待在户外。建议穿防晒服、戴帽子和太阳镜，打遮阳伞，涂抹SPF50+的防晒霜。";
        } else {
            return "今天紫外线指数极高，建议尽量避免外出。如必须外出，请穿防晒服、戴宽檐帽和太阳镜，涂抹SPF50+的防晒霜，并尽量在阴凉处活动。";
        }
    }

    public static String convertWindDirection(int degree) {
        if (degree >= 0 && degree <= 11 || degree >= 349 && degree <= 360) {
            return "北风";
        } else if (degree >= 12 && degree <= 33) {
            return "北东北风";
        } else if (degree >= 34 && degree <= 56) {
            return "东北风";
        } else if (degree >= 57 && degree <= 78) {
            return "东东北风";
        } else if (degree >= 79 && degree <= 101) {
            return "东风";
        } else if (degree >= 102 && degree <= 123) {
            return "东东南风";
        } else if (degree >= 124 && degree <= 146) {
            return "东南风";
        } else if (degree >= 147 && degree <= 168) {
            return "南东南风";
        } else if (degree >= 169 && degree <= 191) {
            return "南风";
        } else if (degree >= 192 && degree <= 213) {
            return "南西南风";
        } else if (degree >= 214 && degree <= 236) {
            return "西南风";
        } else if (degree >= 237 && degree <= 258) {
            return "西西南风";
        } else if (degree >= 259 && degree <= 281) {
            return "西风";
        } else if (degree >= 282 && degree <= 303) {
            return "西西北风";
        } else if (degree >= 304 && degree <= 326) {
            return "西北风";
        } else if (degree >= 327 && degree <= 348) {
            return "北西北风";
        } else {
            return "未知风向";
        }
    }

    public static String convertWindSpeed(double speed) {
        if (speed < 0.3) {
            return "0级（静风）";
        } else if (speed <= 1.5) {
            return "1级（轻风）";
        } else if (speed <= 3.3) {
            return "2级（轻微风）";
        } else if (speed <= 5.4) {
            return "3级（微风）";
        } else if (speed <= 7.9) {
            return "4级（和风）";
        } else if (speed <= 10.7) {
            return "5级（清风）";
        } else if (speed <= 13.8) {
            return "6级（强风）";
        } else if (speed <= 17.1) {
            return "7级（疾风）";
        } else if (speed <= 20.7) {
            return "8级（大风）";
        } else if (speed <= 24.4) {
            return "9级（烈风）";
        } else if (speed <= 28.4) {
            return "10级（狂风）";
        } else if (speed <= 32.6) {
            return "11级（暴风）";
        } else {
            return "12级及以上（台风或飓风）";
        }
    }

    public String getTitle(String location) {
        WeatherResponse weather = getWeather(location);
        String title = "";
        WeatherResponse.Current current = weather.getCurrent();
        WeatherResponse.ForecastDay forecast = weather.getForecast().getForecastday().get(0);
        String nameByType = WeatherEnum.getNameByType(current.getCondition().getText());
        if (nameByType.contains("雨")) {
            title += "今日有雨，记得带伞；";
        }
        if (nameByType.contains("雪")) {
            title += "今日有雪，记得带伞；";
        }
        if (nameByType.contains("霾")) {
            title += "今日有霾，记得带口罩；";
        }
        double minTemp = forecast.getDay().getMintemp_c();
        if (minTemp < -5) {
            title += "天气极寒，建议穿厚羽绒服、毛衣、围巾和手套。";
        } else if (minTemp >= -5 && minTemp < 0) {
            title += "天气寒冷，建议穿羽绒服、厚毛衣和围巾。";
        } else if (minTemp >= 0 && minTemp < 5) {
            title += "温度较低，建议穿厚外套和毛衣。";
        } else if (minTemp >= 5 && minTemp < 10) {
            title += "天气微冷，建议穿卫衣或薄外套。";
        } else if (minTemp >= 10 && minTemp < 15) {
            title += "天气较凉，建议穿轻外套或长袖衣物。";
        } else if (minTemp >= 15 && minTemp < 20) {
            title += "温度适中，建议穿薄外套或长袖衬衫。";
        } else if (minTemp >= 20 && minTemp < 25) {
            title += "天气较暖，建议穿短袖或轻薄的长袖。";
        } else if (minTemp >= 25 && minTemp < 30) {
            title += "天气温暖，建议穿短袖、短裤等轻便服装。";
        } else {
            title += "天气炎热，建议穿清凉的短袖和短裤。";
        }
        return title;
    }
}
